package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.ruoyi.common.annotation.UserDataIsolation;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DataUtils;
import com.ruoyi.common.utils.ExcelUtils;
import com.ruoyi.common.utils.PDFUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.DeviceStatusSummaryVO;
import com.ruoyi.system.domain.vo.QueryVo;
import com.ruoyi.system.domain.vo.SalesSummaryVO;
import com.ruoyi.system.mapper.PointCheckDeviceDetailMapper;
import com.ruoyi.system.mapper.ReportDetailMapper;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.map.LinkedMap;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.FileUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.validation.Valid;
import javax.validation.constraints.Null;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
@Service
@Slf4j
public class ReportDetailServiceImpl implements IReportDetailService {
    @Autowired
    private ReportDetailMapper reportDetailMapper;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private IProductChartService productChartService;
    @Autowired
    private IReportTimedService reportTimedService;
    @Autowired
    private IProductTelemetryService productTelemetryService;
    @Autowired
    private ISysCompanyThingsboardService sysCompanyThingsboardService;
    @Autowired
    private IAsyncDetailService asyncDetailService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private IPointCheckTaskService pointCheckTaskService;
    @Autowired
    private IAlarmService alarmService;
    @Autowired
    private IProductService productService;
    @Autowired
    private ITerminalEventDetailService terminalEventDetailService;

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysDeptService sysDeptService;

    @Autowired
    private PointCheckDeviceDetailMapper pointCheckDeviceDetailMapper;
    //客户角色Id
    @Value("${sysUser.customerRoleId:105}")
    private Long customerRoleId;
    @Autowired
    private ICustomPermissionService customPermissionService;


    @Override
    @UserDataIsolation(tableAlias = "t1")
    public List<ReportDetail> queryList(ReportDetail reportDetail) {
        return reportDetailMapper.queryList(reportDetail);
    }

    @Override
    public Boolean add(ReportDetail reportDetail) {
        return reportDetailMapper.add(reportDetail) > 0;
    }

    @Override
    @Async
    public ReportDetail queryDetail(ReportDetail reportDetail, String tid, SysUser sysUser) {
        //TODO 根据产品和时间查询TB数据接口
        Long companyId = reportDetail.getCompanyId();
        //获取TB信息
        reportDetail.setTid(tid);
        JSONArray choseData = reportDetail.getChoseData();
        List<Map<String, Object>> result = new ArrayList<>();
        //存放产品名称
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < choseData.size(); i++) {
            JSONObject jsonObject = choseData.getJSONObject(i);
            Map<String, Object> map = new HashMap<>();
            if (StrUtil.equals(jsonObject.getString("type"), "1")) {
                //项目报表
                List<Map<String, String>> allColumn = getAllColumn("1");
                QueryVo queryVo = new QueryVo();
                queryVo.filters.put("company_id", companyId);
                String sql = customPermissionService.getProjectAuthorizePermission("p", null, sysUser);
                queryVo.setCustomPermissionSql(sql);
                List<Project> projectList = projectService.index(queryVo);
                map.put("type", "1");
                map.put("sort", "1");
                map.put("allColumn", allColumn);
                map.put("data", projectList);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "2")) {
                //产品报表
                List<Map<String, String>> allColumn = getAllColumn("2");
                QueryVo queryVo = new QueryVo();
                queryVo.filters.put("company_id", companyId);
                List<Product> productList = productService.index(queryVo);
                map.put("type", "2");
                map.put("sort", "2");
                map.put("allColumn", allColumn);
                map.put("data", productList);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "3")) {
                String startTimeStr = jsonObject.getString("startTime");
                String endTimeStr = jsonObject.getString("endTime");
                //报警报表
                List<Map<String, String>> allColumn = getAllColumn("3");
                QueryVo queryVo = new QueryVo();
                if (startTimeStr != null) {
                    queryVo.filters.put("startBegin", startTimeStr);
                }
                if (endTimeStr != null) {
                    queryVo.filters.put("startEnd", endTimeStr);
                }
                queryVo.filters.put("company_id", companyId);
                List<Alarm> alarmList = alarmService.index(queryVo);
                map.put("type", "3");
                map.put("sort", "6");
                map.put("allColumn", allColumn);
                map.put("data", alarmList);
                map.put("startTime", startTimeStr);
                map.put("endTime", endTimeStr);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "4")) {
                String startTimeStr = jsonObject.getString("startTime");
                String endTimeStr = jsonObject.getString("endTime");
                PointCheckTask pointCheckTask = new PointCheckTask();
                pointCheckTask.setStartTimeBegin(DateUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss"));
                pointCheckTask.setStartTimeEnd(DateUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss"));
                //点检任务报表
                List<Map<String, String>> allColumn = getAllColumn("4");
                pointCheckTask.setCompanyId(companyId);
                boolean flag = sysDeptService.checkIsCustomer(sysUser.getDeptId());
                if (flag) {
                    Long customerId = sysDeptService.getCustomerId(sysUser.getDeptId());
                    pointCheckTask.setDeptId(customerId);
                }
                List<PointCheckTask> pointCheckTasks = pointCheckTaskService.queryList(pointCheckTask);
                if (flag){
                    if (CollUtil.isNotEmpty(pointCheckTasks)){
                        pointCheckTasks.forEach(a ->{
                            a.setProjectCode(null);
                        });
                    }
                }
                map.put("type", "4");
                map.put("sort", "7");
                map.put("allColumn", allColumn);
                map.put("data", pointCheckTasks);
                map.put("startTime", startTimeStr);
                map.put("endTime", endTimeStr);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "5")) {
                //产品列表报表
                List<Map<String, String>> allColumn = getAllColumn("5");
                QueryVo queryVo = new QueryVo();
                queryVo.filters.put("company_id", companyId);
                String sql = customPermissionService.getProjectAuthorizePermission("tbl_device", "project_id", sysUser);
                queryVo.setCustomPermissionSql(sql);
//                queryVo.filters.put("discarded", 0);
                //验证当前用户属于客户公司还是总公司
                boolean flag = sysDeptService.checkIsCustomer(sysUser.getDeptId());
                if (flag) {
                    queryVo.filters.put("customer_name", sysUser.getUserName());
                }
                List<Device> deviceList = deviceService.index(queryVo);
                map.put("type", "5");
                map.put("sort", "3");
                map.put("allColumn", allColumn);
                map.put("data", deviceList);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "7")) {
                //产品销售统计
                List<Map<String, String>> allColumn = getAllColumn("7");
                QueryVo queryVo = new QueryVo();
                queryVo.filters.put("company_id", companyId);
                queryVo.filters.put("sysUser", sysUser);
                List<SalesSummaryVO> salesSummaryVOS = salesSummary(queryVo);
                map.put("type", "7");
                map.put("sort", "4");
                map.put("allColumn", allColumn);
                map.put("data", salesSummaryVOS);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "8")) {
                //产品状态统计
                List<Map<String, String>> allColumn = getAllColumn("8");
                QueryVo queryVo = new QueryVo();
                queryVo.filters.put("company_id", companyId);
                queryVo.filters.put("sysUser", sysUser);
                //验证当前用户是否是客户
                Long deptId = null;
                boolean flag = sysDeptService.checkIsCustomer(sysUser.getDeptId());
                if (flag) {
                    //取客户部门id
                    deptId = sysDeptService.getCustomerId(sysUser.getDeptId());
                    queryVo.filters.put("dept_id", deptId);
                }
                List<DeviceStatusSummaryVO> deviceStatusSummaryVOS = deviceStatusSummary(queryVo);
                map.put("type", "8");
                map.put("sort", "5");
                map.put("allColumn", allColumn);
                map.put("data", deviceStatusSummaryVOS);
                result.add(map);
            }
            if (StrUtil.equals(jsonObject.getString("type"), "6")) {
                //产品数据报表
                JSONArray data = jsonObject.getJSONArray("dataDetail");
                String startTimeStr = jsonObject.getString("startTime");
                String endTimeStr = jsonObject.getString("endTime");
                log.info("startTime", startTimeStr);
                log.info("endTime", endTimeStr);
                long start = DateUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss").getTime();
                long end = DateUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss").getTime();
                SysCompanyThingsboard sysCompanyThingsboard = sysCompanyThingsboardService.selectSysCompanyThingsboardByCompanyId(companyId);
                List<List<Map<String, Object>>> resultData = new ArrayList<>();
                for (int j = 0; j < data.size(); j++) {
                    List<Map<String, Object>> deviceData = new ArrayList<>();
                    JSONObject dataDetailJSONObject = data.getJSONObject(j);
                    //获取产品Id
                    Integer deviceId = dataDetailJSONObject.getInteger("deviceId");
                    //获取数据类型，1点位数据，2活跃统计，3事件数据
                    String number = dataDetailJSONObject.getString("number");
                    if (StrUtil.isBlank(number)) {
                        continue;
                    }
                    QueryVo vo = new QueryVo();
                    vo.filters.put("id", deviceId);
                    Device device = deviceService.retrieve(vo);
                    if (device == null) {
                        continue;
                    }
                    sb.append(device.getName()).append("|").append(deviceId).append("&");
                    if (number.contains("1")) {
                        Map<String, Object> mapData = new HashMap<>();
                        Integer productId = device.getProductId();
                        //根据产品Id查询点位信息
                        QueryVo queryVo = new QueryVo();
                        queryVo.filters.put("product_id", productId);
                        queryVo.filters.put("company_id", companyId);
                        List<ProductTelemetry> telemetries = productTelemetryService.index(queryVo);
                        if (CollUtil.isEmpty(telemetries)) {
                            continue;
                        }
                        List<String> identifiers = telemetries.stream().map(ProductTelemetry::getUserIdentifier).collect(Collectors.toList());
                        log.info("点位信息{}", identifiers);
                        vo.filters.clear();
                        vo.filters.put("start", start);
                        vo.filters.put("end", end);
                        vo.filters.put("identifiers", identifiers);
                        vo.filters.put("aggregation", "NONE");
                        log.info("{}", sysCompanyThingsboard);
                        JSONArray dataArray = deviceService.historicalTimeSeries(device, vo, sysCompanyThingsboard);
                        log.info("产品号{}点位数据{}", deviceId, dataArray);
                        dataArray = dataArray == null ? new JSONArray() : dataArray;
                        mapData.put("device", device);
                        mapData.put("data", dataArray);
                        mapData.put("identifiers", identifiers);
                        mapData.put("telemetries", telemetries);
                        mapData.put("number", "1");
                        deviceData.add(mapData);
                    }
                    if (number.contains("2")) {
                        Map<String, Object> mapData = new HashMap<>();
                        List<String> identifiers = new ArrayList<>();
                        List<String> columns = new ArrayList<>();
                        List<DeviceTerminal> terminals = device.getTerminals();
                        if (CollUtil.isNotEmpty(terminals)) {
                            for (int k = 0; k < terminals.size(); k++) {
                                DeviceTerminal deviceTerminal = terminals.get(k);
                                identifiers.add("__active__" + deviceTerminal.getProductTerminalNumber());
                                columns.add(deviceTerminal.getProductTerminalName() + "在线状态（__active__" + deviceTerminal.getProductTerminalNumber() + "）");
                            }
                            log.info("活跃统计信息{}", identifiers);
                            vo.filters.clear();
                            vo.filters.put("start", start);
                            vo.filters.put("end", end);
                            vo.filters.put("identifiers", identifiers);
                            vo.filters.put("aggregation", "NONE");
                            JSONArray dataArray = deviceService.historicalTimeSeries(device, vo, sysCompanyThingsboard);
                            log.info("产品号{}活跃数据{}", deviceId, dataArray);
                            dataArray = dataArray == null ? new JSONArray() : dataArray;
                            mapData.put("device", device);
                            mapData.put("data", dataArray);
                            mapData.put("identifiers", identifiers);
                            mapData.put("columns", columns);
                            mapData.put("number", "2");
                            deviceData.add(mapData);
                        }
                    }
                    if (number.contains("3")) {
                        Map<String, Object> mapData = new HashMap<>();
                        TerminalEventDetail terminalEventDetail = new TerminalEventDetail();
                        terminalEventDetail.setDeviceId(deviceId);
                        terminalEventDetail.setCreateTimeStart(DateUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss"));
                        terminalEventDetail.setCreateTimeEnd(DateUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss"));
                        terminalEventDetail.setCompanyId(companyId);
                        List<TerminalEventDetail> terminalEventDetails = terminalEventDetailService.queryList(terminalEventDetail);
                        List<Map<String, String>> allColumn = getAllColumn("sj");
                        mapData.put("device", device);
                        mapData.put("data", terminalEventDetails);
                        mapData.put("identifiers", allColumn);
                        mapData.put("number", "3");
                        deviceData.add(mapData);
                    }
                    resultData.add(deviceData);
                }
                map.put("type", "6");
                map.put("sort", "8");
                map.put("data", resultData);
                map.put("startTime", startTimeStr);
                map.put("endTime", endTimeStr);
                result.add(map);
            }
        }
        if (CollUtil.isEmpty(result)) {
            //TODO 生成失败，没有获取到产品或点位信息
            asyncDetailService.update(tid, 2, "没有获取到产品或点位信息");
            return reportDetail;
        }
        Collections.sort(result, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                String type1 = (String) o1.get("sort");
                String type2 = (String) o2.get("sort");
                return type1.compareTo(type2);
            }
        });
        String deviceName = null;
        if (sb.toString().length() > 0) {
            deviceName = sb.toString().substring(0, sb.toString().length() - 1);
        }
        //处理结果数据
        ReportDetail excel = reportDetail;
        try {
            if (StrUtil.equals("xlsx", reportDetail.getForm())) {
                //生成Excel
                excel = createExcel(reportDetail, result, deviceName);
            } else {
                //TODO 生成PDF
                excel = createPdf(reportDetail, result);
            }
            asyncDetailService.update(tid, 1, excel.getUrl());
        } catch (Exception e) {
            log.error(e.getMessage());
            asyncDetailService.update(tid, 2, e.getMessage());
        }
        reportDetailMapper.update(excel);
        return excel;
    }

    private ReportDetail createPdf(ReportDetail reportDetail, List<Map<String, Object>> result) {
        Date now = new Date();
        String filePath = RuoYiConfig.getUploadPath();
        //filePath = "E://excel//";
        SimpleDateFormat sdfs = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String fileUrl = String.format(filePath + reportDetail.getName() + "%s.pdf", sdfs.format(now));
        Document document = PDFUtils.createDocument(fileUrl);
        for (Map<String, Object> map : result) {
            String type = (String) map.get("type");
            if (StrUtil.equals(type, "1")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Project> projectList = (List<Project>) map.get("data");
                List<List<Map<String, String>>> projectData = getProjectData(allColumn, projectList);
                PDFUtils.createNotDataList(document, allColumn, "项目统计", projectData);
            }
            if (StrUtil.equals(type, "2")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Product> projectList = (List<Product>) map.get("data");
                List<List<Map<String, String>>> productData = getProductData(allColumn, projectList);
                PDFUtils.createNotDataList(document, allColumn, "型号统计", productData);
            }
            if (StrUtil.equals(type, "3")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Alarm> alarmList = (List<Alarm>) map.get("data");
                String startTime = (String) map.get("startTime");
                String endTime = (String) map.get("endTime");
                List<List<Map<String, String>>> alarmData = getAlarmData(allColumn, alarmList);
                PDFUtils.createDataList(document, allColumn, "报警统计", alarmData, startTime, endTime);
            }
            if (StrUtil.equals(type, "4")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<PointCheckTask> projectList = (List<PointCheckTask>) map.get("data");
                String startTime = (String) map.get("startTime");
                String endTime = (String) map.get("endTime");
                List<List<Map<String, String>>> pointCheckData = getPointCheckData(allColumn, projectList);
                PDFUtils.createDataList(document, allColumn, "点检任务完成进度", pointCheckData, startTime, endTime);
            }
            if (StrUtil.equals(type, "5")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Device> deviceList = (List<Device>) map.get("data");
                List<List<Map<String, String>>> deviceData = getDeviceData(allColumn, deviceList);
                PDFUtils.createNotDataList(document, allColumn, "产品统计", deviceData);
            }
            if (StrUtil.equals(type, "7")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<SalesSummaryVO> salesSummaryVOS = (List<SalesSummaryVO>) map.get("data");
                List<List<Map<String, String>>> salesSummaryData = getSalesSummaryData(allColumn, salesSummaryVOS);
                PDFUtils.createNotDataList(document, allColumn, "产品销售汇总", salesSummaryData);
            }
            if (StrUtil.equals(type, "8")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<DeviceStatusSummaryVO> deviceStatusSummaryVOS = (List<DeviceStatusSummaryVO>) map.get("data");
                List<List<Map<String, String>>> deviceStatusSummaryData = getDeviceStatusSummaryData(allColumn, deviceStatusSummaryVOS);
                PDFUtils.createNotDataList(document, allColumn, "产品运行状态汇总", deviceStatusSummaryData);
            }
            if (StrUtil.equals(type, "6")) {
                List<List<Map<String, Object>>> resultData = (List<List<Map<String, Object>>>) map.get("data");
                String startTime = (String) map.get("startTime");
                String endTime = (String) map.get("endTime");
                if (CollUtil.isEmpty(resultData)) {
                    continue;
                }
                List<List<Map<String, Object>>> detailList = new ArrayList<>();
                for (List<Map<String, Object>> dateMap2 : resultData) {
                    List<Map<String, Object>> mapList = new ArrayList<>();
                    for (Map<String, Object> mapDetail : dateMap2) {
                        String number = (String) mapDetail.get("number");
                        //点位数据
                        if (StrUtil.equals(number, "1")) {
                            Device device = (Device) mapDetail.get("device");
                            JSONArray jsonArray = (JSONArray) mapDetail.get("data");
                            List<ProductTelemetry> telemetries = (List<ProductTelemetry>) mapDetail.get("telemetries");
                            List<String> identifiers = (List<String>) mapDetail.get("identifiers");
                            identifiers.add(0, "日期");
                            identifiers.add(1, "时间");
                            List<List<Map<String, String>>> rows = getPDFData(identifiers, jsonArray);
                            List<String> row0CellName = getRow0CellName(identifiers, telemetries);
                            row0CellName.add(0, "日期");
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put("number", "1");
                            map1.put("columns", row0CellName);
                            map1.put("data", rows);
                            map1.put("deviceName", device.getName());
                            mapList.add(map1);
                        }
                        //活跃度数据
                        if (StrUtil.equals(number, "2")) {
                            Device device = (Device) mapDetail.get("device");
                            JSONArray jsonArray = (JSONArray) mapDetail.get("data");
                            List<String> identifiers = (List<String>) mapDetail.get("identifiers");
                            identifiers.add(0, "日期");
                            identifiers.add(1, "时间");
                            List<String> columns = (List<String>) mapDetail.get("columns");
                            columns.add(0, "日期");
                            columns.add(1, "时间");
                            List<List<Map<String, String>>> activeData = getPDFData(identifiers, jsonArray);
                            log.info("产品名称{}，PDF活跃度数据{}", device.getName(), activeData);
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put("number", "2");
                            map1.put("columns", columns);
                            map1.put("data", activeData);
                            map1.put("deviceName", device.getName());
                            mapList.add(map1);
                        }
                        //事件数据
                        if (StrUtil.equals(number, "3")) {
                            Device device = (Device) mapDetail.get("device");
                            List<TerminalEventDetail> terminalEventDetails = (List<TerminalEventDetail>) mapDetail.get("data");
                            List<Map<String, String>> allColumn = (List<Map<String, String>>) mapDetail.get("identifiers");
                            List<List<Map<String, String>>> eventData = getEventData(allColumn, terminalEventDetails);
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put("number", "3");
                            map1.put("columns", allColumn);
                            map1.put("data", eventData);
                            map1.put("deviceName", device.getName());
                            mapList.add(map1);
                        }
                    }
                    detailList.add(mapList);

                }
                PDFUtils.createDeviceDate(document, detailList, startTime, endTime);
            }
        }
//        boolean pdfFlag = PDFUtils.createDeviceDatePdf(document, data, DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss"), DateUtil.format(endTime, "yyyy-MM-dd HH:mm:ss"), deviceName);
        document.close();
        try {
            File file = new File(fileUrl);
            DiskFileItem item = new DiskFileItem("file"
                    , MediaType.MULTIPART_FORM_DATA_VALUE
                    , true
                    , file.getName()
                    , (int) file.length()
                    , file.getParentFile());
            OutputStream os = item.getOutputStream();
            os.write(FileUtils.readFileToByteArray(file));
            MultipartFile multipartFile = new CommonsMultipartFile(item);
            String fileName = FileUploadUtils.upload(filePath, multipartFile);
            log.info("文件名称{}", fileName);
            reportDetail.setUrl(fileName);
            file.delete();
        } catch (Exception e) {
            throw new CustomException(e.getMessage());
        }
        return reportDetail;
    }

    /**
     * 获取生成PDF数据
     *
     * @param identifiers
     * @param jsonArray
     * @return
     */
    private List<List<Map<String, String>>> getPDFData(List<String> identifiers, JSONArray jsonArray) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            List<Map<String, String>> dataValue = new ArrayList<>();
            for (String identifier : identifiers) {
                Map<String, String> map = new HashMap<>();
                if (StrUtil.equals(identifier, "日期")) {
                    String value = jsonObject.getString("time");
                    map.put("data", DateUtil.format(DateUtil.parse(value, "yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd"));
                    map.put("name", "time");
                    dataValue.add(map);

                    map = new HashMap<>();
                    map.put("data", DateUtil.format(DateUtil.parse(value, "yyyy-MM-dd HH:mm:ss"), "HH:mm:ss"));
                    map.put("name", "time");
                    dataValue.add(map);
                    continue;
                }
                if (StrUtil.equals(identifier, "时间")) {
                    continue;
                }
                String value = jsonObject.getString(identifier);
                if (StrUtil.isBlank(value)) {
                    map.put("data", "");
                    map.put("name", identifier);
                } else {
                    map.put("data", value);
                    map.put("name", identifier);
                }
                dataValue.add(map);
            }
            result.add(dataValue);
        }
        return result;
    }

    @Override
    @Scheduled(cron = "0 10 02 * * ?")
    public void createTimedReport() {
        ReportTimed param = new ReportTimed();
        Date nowDate = new Date();
        //获取昨天时间
        DateTime offset = DateUtil.offsetDay(nowDate, -1);
        // TODO 昨天结束时间，作为查询结束时间
        DateTime endOfDay = DateUtil.endOfDay(offset);
        DateTime beginOfDay = DateUtil.beginOfDay(nowDate);
        //获取当天是这周的第几天，当天是这月的第几天
        int dayOfWeek = DateUtil.dayOfWeek(nowDate);
        dayOfWeek = dayOfWeek == 1 ? 7 : dayOfWeek - 1;
        int dayOfMonth = DateUtil.dayOfMonth(nowDate);
        List<ReportTimed> reportTimeds = reportTimedService.queryList(param);
        if (CollUtil.isEmpty(reportTimeds)) {
            return;
        }
        for (ReportTimed reportTimed : reportTimeds) {
            Integer timedId = reportTimed.getId();
            String periodic = reportTimed.getPeriodic();
            Date startTime = null;
            if (StrUtil.equals("每天", periodic)) {
                startTime = DateUtil.offsetDay(beginOfDay, -1);
            } else if (StrUtil.equals("每周", periodic)) {
                if (dayOfWeek != 1) {
                    continue;
                }
                startTime = DateUtil.offsetWeek(beginOfDay, -1);
            } else {
                //每月
                if (dayOfMonth != 1) {
                    continue;
                }
                startTime = DateUtil.offsetMonth(beginOfDay, -1);
            }
            //开始查询
            //获取用户id
            String createBy = reportTimed.getCreateBy();
            SysUser sysUser = sysUserService.selectUserByUserName(createBy);
            ReportDetail reportDetail = new ReportDetail();
            reportDetail.setReportId(timedId);
            reportDetail.setType("1");
            reportDetail.setCompanyId(reportTimed.getCompanyId());
            reportDetail.setCreateTime(new Date());
            reportDetail.setCreateBy(reportTimed.getCreateBy());
            String data = reportTimed.getData();
            reportDetail.setData(data);
            if (StrUtil.isBlank(data)) {
                continue;
            }
            cn.hutool.json.JSONArray jsonArray = JSONUtil.parseArray(data);
            for (int i = 0; i < jsonArray.size(); i++) {
                cn.hutool.json.JSONObject jsonObject = jsonArray.get(i, cn.hutool.json.JSONObject.class);
                if (StrUtil.equals(jsonObject.getStr("type"), "3") || StrUtil.equals(jsonObject.getStr("type"), "4") || StrUtil.equals(jsonObject.getStr("type"), "6")) {
                    jsonObject.set("startTime", DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss"));
                    jsonObject.set("endTime", DateUtil.format(endOfDay, "yyyy-MM-dd HH:mm:ss"));
                }
            }
            reportDetail.setChoseData(JSONArray.parseArray(JSONUtil.toJsonStr(jsonArray)));
//            reportDetail.setDeviceId(reportTimed.getDeviceId());
//            reportDetail.setEndTime(endOfDay);
//            reportDetail.setStartTime(startTime);
            reportDetail.setForm(reportTimed.getForm());
//            reportDetail.setIdentifier(reportTimed.getIdentifier());
            reportDetail.setName(reportTimed.getName());
            reportDetail.setPeriodic(reportTimed.getPeriodic());
//            reportDetail.setReceiver(reportTimed.getReceiver());
            String tid = asyncDetailService.createTid("定时报表功能", reportTimed.getCompanyId());
            //添加
            add(reportDetail);
            queryDetail(reportDetail, tid, sysUser);
        }
    }

    @Override
    public List<SalesSummaryVO> salesSummary(QueryVo queryVo) {
        SysUser sysUser = (SysUser) queryVo.filters.get("sysUser");
        //验证当前用户是否是客户
        Long deptId = null;
        boolean flag = sysDeptService.checkIsCustomer(sysUser.getDeptId());
        if (flag) {
            //取客户部门id
            deptId = sysDeptService.getCustomerId(sysUser.getDeptId());
            queryVo.filters.put("dept_id", deptId);
        }
        List<SalesSummaryVO> salesSummaryVOS = reportDetailMapper.salesSummary(queryVo);
        if (CollUtil.isEmpty(salesSummaryVOS)) {
            return new ArrayList<>();
        }
        List<SalesSummaryVO> result = new ArrayList<>();
        Map<String, List<SalesSummaryVO>> collect = salesSummaryVOS.stream().collect(Collectors.groupingBy(SalesSummaryVO::getProjectCode));
        for (Map.Entry<String, List<SalesSummaryVO>> entry : collect.entrySet()) {
            List<SalesSummaryVO> value = entry.getValue();
            if (CollUtil.isNotEmpty(value)) {
                SalesSummaryVO salesSummaryVO = value.get(0);
                salesSummaryVO.setDeviceNum(value.size());
                result.add(salesSummaryVO);
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> pointCheckStatusSummary(QueryVo queryVo, Map<String, Object> options) {
        List<Map<String, Object>> result = new ArrayList<>();
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        //验证当前用户是否是客户
        Long deptId = null;
        boolean flag = sysDeptService.checkIsCustomer(sysUser.getDeptId());
        if (flag) {
            //取客户部门id
            deptId = sysDeptService.getCustomerId(sysUser.getDeptId());
            queryVo.filters.put("dept_id", deptId);
        }
        List<SalesSummaryVO> salesSummaryVOS = reportDetailMapper.salesSummary(queryVo);
        Map<String, Map<String, Integer>> resultMap = new LinkedMap<>();
        for (SalesSummaryVO summaryVO : salesSummaryVOS) {
            String projectName = summaryVO.getProjectName();
            if (projectName == null) {
                continue;
            }
            Map<String, Integer> projectSummary = resultMap.get(projectName);
            if (projectSummary == null) {
                projectSummary = new LinkedMap<>();
                projectSummary.put("normal", 0);
                projectSummary.put("abnormal", 0);
                resultMap.put(projectName, projectSummary);
            }
            //查询最新检查信息
            String sn = summaryVO.getSn();
            QueryVo vo = new QueryVo();
            vo.filters.put("sn", sn);
            List<Map<String, Object>> errorAddresses = reportDetailMapper.queryErrorAddress(vo);
            if (errorAddresses.size() > 0) {
                projectSummary.put("abnormal", projectSummary.get("abnormal") + 1);
            } else {
                projectSummary.put("normal", projectSummary.get("normal") + 1);
            }
        }
        Set<String> keys = resultMap.keySet();
        for (String key : keys) {
            Map<String, Integer> mapItem = resultMap.get(key);
            Map<String, Object> resultItem = new HashMap<>();
            resultItem.put("项目", key);
            resultItem.put("正常", mapItem.get("normal"));
            resultItem.put("异常", mapItem.get("abnormal"));
            result.add(resultItem);
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> pointCheckAbnormalSummaryByMonth(QueryVo queryVo, Map<String, Object> options) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        Long deptId = null;
        boolean flag = sysDeptService.checkIsCustomer(sysUser.getDeptId());
        if (flag) {
            deptId = sysDeptService.getCustomerId(sysUser.getDeptId());
            queryVo.filters.put("dept_id", deptId);
        }
        List<Map<String, Object>> values = new ArrayList<>();
        try {
            List<String> months = null;
            Date start = queryVo.filters.getDate("start");
            if (start != null) {
                months = new ArrayList<>();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(start);
                Date now = new Date();
                while (calendar.getTime().before(now)) {
                    months.add(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                }
            }
            Map<String, Object> regulatedOptions = new HashMap<>();
            regulatedOptions.put("month", "label");
            regulatedOptions.put("count", "value");
            List<Map<String, Object>> monthValues = pointCheckDeviceDetailMapper.pointCheckAbnormalSummaryByMonth(queryVo);
            if (months != null) {
                for (String month : months) {
                    Boolean found = false;
                    for (Map<String, Object> item : monthValues) {
                        if (item.get("month").toString().equals(month)) {
                            Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                            values.add(DataUtils.KVconvertKey(regulated, options));
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        Map<String, Object> item = new HashMap<>();
                        item.put("month", month);
                        item.put("count", 0);
                        Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                        values.add(DataUtils.KVconvertKey(regulated, options));
                    }
                }
            } else {
                for (Map<String, Object> item : monthValues) {
                    Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                    values.add(DataUtils.KVconvertKey(regulated, options));
                }
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return values;
    }

    @Override
    public List<DeviceStatusSummaryVO> deviceStatusSummary(QueryVo queryVo) {

        List<DeviceStatusSummaryVO> deviceStatusSummaryVOS = reportDetailMapper.queryDeviceStatusVO(queryVo);
        if (CollUtil.isEmpty(deviceStatusSummaryVOS)) {
            return new ArrayList<>();
        }
        Map<String, List<DeviceStatusSummaryVO>> resultMap = deviceStatusSummaryVOS.stream().collect(Collectors.groupingBy(DeviceStatusSummaryVO::getSn));
        for (Map.Entry<String, List<DeviceStatusSummaryVO>> entry : resultMap.entrySet()) {
            String sn = entry.getKey();
            QueryVo vo = new QueryVo();
            vo.filters.put("sn",sn);
            vo.filters.put("begin",queryVo.filters.getDate("begin"));
            vo.filters.put("end",queryVo.filters.getDate("end"));
            List<Map<String, Object>> mapList = reportDetailMapper.queryDeviceDealTimes(vo);
            List<Map<String, Object>> dealTimeList = mapList.stream().filter(a -> a.get("dealId") != null).collect(Collectors.toList());
            Integer dealTimes;
            if (CollUtil.isEmpty(dealTimeList)){
                dealTimes = 0;
            }else {
                dealTimes = dealTimeList.size();
            }
            List<DeviceStatusSummaryVO> value = entry.getValue();
            for (DeviceStatusSummaryVO statusSummaryVO : value) {
                String type = statusSummaryVO.getType();
                String item = statusSummaryVO.getItem();
                String detail = statusSummaryVO.getDetail();
//                if (StrUtil.equals("波纹管", type) && (StrUtil.equals("腐蚀", item) || StrUtil.equals("异常变形", item))) {
//                    if (StrUtil.isNotBlank(detail)) {
//                        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(detail);
//                        //handle true 需要处理  false  不需要处理
//                        Boolean handle = jsonObject.getBool("handle", true);
//                        //需要处理
//                        if (handle) {
//                            if (statusSummaryVO.getDealId() != null) {
//                                statusSummaryVO.setDeal(true);
//                            }
//                        } else {
//                            //不需要处理
//                            statusSummaryVO.setDeal(true);
//                        }
//                    }}
                if (statusSummaryVO.getDealId() != null) {
                    statusSummaryVO.setDeal(true);
                }
                StringBuilder sb = new StringBuilder();
                if (StrUtil.isNotBlank(type)){
                    String errorAddress = sb.append(type).append("-").append(item).toString();
                    statusSummaryVO.setErrorAddress(errorAddress);
                }
                statusSummaryVO.setDealTimes(dealTimes);
            }
        }
        return deviceStatusSummaryVOS;
    }


    /**
     * 生成Excel表格并上传
     *
     * @param reportDetail
     * @param data         统计数据
     * @return
     */
    private ReportDetail createExcel(ReportDetail reportDetail, List<Map<String, Object>> data, String deviceName) {
        Workbook wb = new XSSFWorkbook();
        //生成概况
        creatSheet0(wb, reportDetail, deviceName);
        for (Map<String, Object> map : data) {
            String type = (String) map.get("type");
            if (StrUtil.equals(type, "1")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Project> projectList = (List<Project>) map.get("data");
                List<List<Map<String, String>>> projectData = getProjectData(allColumn, projectList);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "项目统计", projectData);
            }
            if (StrUtil.equals(type, "2")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Product> projectList = (List<Product>) map.get("data");
                List<List<Map<String, String>>> productData = getProductData(allColumn, projectList);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "型号统计", productData);
            }
            if (StrUtil.equals(type, "3")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Alarm> alarmList = (List<Alarm>) map.get("data");
                List<List<Map<String, String>>> alarmData = getAlarmData(allColumn, alarmList);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "报警统计", alarmData);
            }
            if (StrUtil.equals(type, "4")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<PointCheckTask> projectList = (List<PointCheckTask>) map.get("data");
                List<List<Map<String, String>>> pointCheckData = getPointCheckData(allColumn, projectList);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "点检任务完成进度", pointCheckData);
            }
            if (StrUtil.equals(type, "5")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<Device> deviceList = (List<Device>) map.get("data");
                List<List<Map<String, String>>> deviceData = getDeviceData(allColumn, deviceList);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "产品统计", deviceData);
            }
            if (StrUtil.equals(type, "7")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<SalesSummaryVO> salesSummaryVOS = (List<SalesSummaryVO>) map.get("data");
                List<List<Map<String, String>>> deviceData = getSalesSummaryData(allColumn, salesSummaryVOS);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "产品销售汇总", deviceData);
            }
            if (StrUtil.equals(type, "8")) {
                List<Map<String, String>> allColumn = (List<Map<String, String>>) map.get("allColumn");
                List<DeviceStatusSummaryVO> salesSummaryVOS = (List<DeviceStatusSummaryVO>) map.get("data");
                List<List<Map<String, String>>> deviceData = getDeviceStatusSummaryData(allColumn, salesSummaryVOS);
                ExcelUtils.CreateWorkbookDetail(wb, allColumn, "产品运行状态汇总", deviceData);
            }
            if (StrUtil.equals(type, "6")) {
                List<List<Map<String, Object>>> dataList = (List<List<Map<String, Object>>>) map.get("data");
                if (CollUtil.isEmpty(dataList)) {
                    continue;
                }
                for (List<Map<String, Object>> dateMap : dataList) {
                    for (Map<String, Object> objectMap : dateMap) {
                        String number = (String) objectMap.get("number");
                        //点位数据
                        if (StrUtil.equals(number, "1")) {
                            Device device = (Device) objectMap.get("device");
                            JSONArray jsonArray = (JSONArray) objectMap.get("data");
                            List<ProductTelemetry> telemetries = (List<ProductTelemetry>) objectMap.get("telemetries");
                            List<String> identifiers = (List<String>) objectMap.get("identifiers");
                            identifiers.add(0, "时间");
                            List<List<Map<String, String>>> rows = getData(identifiers, jsonArray, telemetries);
                            List<String> row0CellName = getRow0CellName(identifiers, telemetries);
                            ExcelUtils.CreateWorkbook(wb, row0CellName, device.getName() + "点位数据", rows, device.getSn());
                        }
                        //活跃度数据
                        if (StrUtil.equals(number, "2")) {
                            Device device = (Device) objectMap.get("device");
                            JSONArray jsonArray = (JSONArray) objectMap.get("data");
                            List<String> identifiers = (List<String>) objectMap.get("identifiers");
                            identifiers.add(0, "时间");
                            List<String> columns = (List<String>) objectMap.get("columns");
                            columns.add(0, "时间");
                            List<List<Map<String, String>>> activeData = getActiveData(identifiers, jsonArray);
                            ExcelUtils.CreateEventWorkbook(wb, columns, device.getName(), activeData, device.getSn());
                        }
                        //事件数据
                        if (StrUtil.equals(number, "3")) {
                            Device device = (Device) objectMap.get("device");
                            List<TerminalEventDetail> terminalEventDetails = (List<TerminalEventDetail>) objectMap.get("data");
                            List<Map<String, String>> allColumn = (List<Map<String, String>>) objectMap.get("identifiers");
                            List<List<Map<String, String>>> eventData = getEventData(allColumn, terminalEventDetails);
                            ExcelUtils.CreateWorkbookEvent(wb, allColumn, device.getName() + "事件数据", eventData, device.getSn());
                        }
                    }

                }
            }
//            Device device = (Device) map.get("device");
//            List<ProductTelemetry> telemetries = (List<ProductTelemetry>) map.get("telemetries");
//            List<String> identifiers = (List<String>) map.get("identifiers");
//            List<String> activeList = (List<String>) map.get("activeList");
//            JSONArray jsonArray = (JSONArray) map.get("data");
//            identifiers.add(0, "时间");
//            List<List<Map<String, String>>> rows = getData(identifiers, jsonArray, telemetries);
//            List<String> row0CellName = getRow0CellName(identifiers, telemetries, activeList);
//            ExcelUtils.CreateWorkbook(wb, row0CellName, device.getName(), rows);
        }
        Date now = new Date();
        SimpleDateFormat sdfs = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String filename = String.format(reportDetail.getName() + "%s.xlsx", sdfs.format(now));
        MultipartFile file = workbookToMf(wb, filename);
        // 上传文件路径
        String filePath = RuoYiConfig.getUploadPath();
        //filePath = "E://excel";
        try {
            String fileName = FileUploadUtils.upload(filePath, file);
            log.info("文件名称{}", fileName);
            reportDetail.setUrl(fileName);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new CustomException("报表上传失败：" + e.getMessage());
        }
        return reportDetail;
    }

    /**
     * 获取Row0的列名
     *
     * @param identifiers
     * @param telemetries
     * @return
     */
    private List<String> getRow0CellName(List<String> identifiers, List<ProductTelemetry> telemetries) {
        List<String> columns = new ArrayList<>();
        columns.add("时间");
        for (String identifier : identifiers) {
            telemetries.forEach(a -> {
                if (StrUtil.equals(a.getUserIdentifier(), identifier)) {
                    columns.add(a.getName() + "(" + identifier + ")");
                }
            });
        }
        return columns;
    }

    /**
     * 生成概况
     *
     * @param wb
     * @param
     * @param reportDetail
     */
    private void creatSheet0(Workbook wb, ReportDetail reportDetail, String deviceName) {
        List<String> deviceNameList = new ArrayList<>();
        if (StrUtil.isNotBlank(deviceName)) {
            deviceNameList = StrUtil.splitTrim(deviceName, "&");
        }
        List<List<String>> sheet0Data = new ArrayList<>();
        //没有时间的列表数据
        List<List<String>> lineDateNotDate = new ArrayList<>();
        //有时间的列表数据
        List<List<String>> lineAlarmDate = new ArrayList<>();
        List<List<String>> linePointCheckDate = new ArrayList<>();
        JSONArray choseData = reportDetail.getChoseData();
        for (int i = 0; i < choseData.size(); i++) {
            JSONObject jsonObject = choseData.getJSONObject(i);
            String type = jsonObject.getString("type");
            if (StrUtil.equals(type, "1")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("项目统计");
                lineDateNotDate.add(detailRow);
            }
            if (StrUtil.equals(type, "2")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("型号统计");
                lineDateNotDate.add(detailRow);
            }
            if (StrUtil.equals(type, "3")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("报警统计");
                lineAlarmDate.add(detailRow);
                List<String> detailStartTimeRow = new ArrayList<>();
                detailStartTimeRow.add("开始时间");
                String startTime = jsonObject.getString("startTime");
                detailStartTimeRow.add(startTime);
                lineAlarmDate.add(detailStartTimeRow);
                List<String> detailEndTimeRow = new ArrayList<>();
                detailEndTimeRow.add("结束时间");
                String endTime = jsonObject.getString("endTime");
                detailEndTimeRow.add(endTime);
                lineAlarmDate.add(detailEndTimeRow);
            }
            if (StrUtil.equals(type, "4")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("点检任务完成进度");
                linePointCheckDate.add(detailRow);
                List<String> detailStartTimeRow = new ArrayList<>();
                detailStartTimeRow.add("开始时间");
                String startTime = jsonObject.getString("startTime");
                detailStartTimeRow.add(startTime);
                linePointCheckDate.add(detailStartTimeRow);
                List<String> detailEndTimeRow = new ArrayList<>();
                detailEndTimeRow.add("结束时间");
                String endTime = jsonObject.getString("endTime");
                detailEndTimeRow.add(endTime);
                linePointCheckDate.add(detailEndTimeRow);
            }
            if (StrUtil.equals(type, "5")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("产品统计");
                lineDateNotDate.add(detailRow);
            }
            if (StrUtil.equals(type, "7")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("产品销售汇总");
                lineDateNotDate.add(detailRow);
            }
            if (StrUtil.equals(type, "8")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("产品运行状态汇总");
                lineDateNotDate.add(detailRow);
            }
            if (StrUtil.equals(type, "6")) {
                List<String> detailRow = new ArrayList<>();
                detailRow.add("数据类型");
                detailRow.add("产品数据统计");
                sheet0Data.add(detailRow);
                List<String> detailStartTimeRow = new ArrayList<>();
                detailStartTimeRow.add("开始时间");
                String startTime = jsonObject.getString("startTime");
                detailStartTimeRow.add(startTime);
                sheet0Data.add(detailStartTimeRow);
                List<String> detailEndTimeRow = new ArrayList<>();
                detailEndTimeRow.add("结束时间");
                String endTime = jsonObject.getString("endTime");
                detailEndTimeRow.add(endTime);
                sheet0Data.add(detailEndTimeRow);
                JSONArray dataDetail = jsonObject.getJSONArray("dataDetail");
                for (int j = 0; j < dataDetail.size(); j++) {
                    JSONObject dataDetailJSONObject = dataDetail.getJSONObject(j);
                    String deviceId = dataDetailJSONObject.getString("deviceId");
                    String name = null;
                    for (String str : deviceNameList) {
                        if (str.contains("|" + deviceId)) {
                            name = StrUtil.splitTrim(str, "|").get(0);
                        }
                    }
                    StringBuilder sb = new StringBuilder();
                    String number = dataDetailJSONObject.getString("number");
                    if (number.contains("1")) {
                        sb.append("点位统计、");
                    }
                    if (number.contains("2")) {
                        sb.append("活跃统计、");
                    }
                    if (number.contains("3")) {
                        sb.append("事件统计、");
                    }
                    String dateStr = null;
                    if (sb.toString().length() > 0) {
                        dateStr = sb.toString().substring(0, sb.toString().length() - 1);
                    }
                    List<String> deviceList = new ArrayList<>();
                    deviceList.add(name);
                    deviceList.add(dateStr);
                    sheet0Data.add(deviceList);
                }
            }
        }

        if (lineDateNotDate.size() > 1) {
            for (int i = 0; i < lineDateNotDate.size(); i++) {
                if (i >= 1) {
                    List<String> data = lineDateNotDate.get(i);
                    data.set(0, "");
                }
            }
        }
        ExcelUtils.CreateSheet0(wb, "概况", sheet0Data, lineDateNotDate, lineAlarmDate, linePointCheckDate);
    }

    /**
     * 将Workbook对象转换成MultipartFile对象
     *
     * @param wb
     * @param fileName
     * @return
     */
    private MultipartFile workbookToMf(Workbook wb, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem textField = factory.createItem("textField", "text/plan", true, fileName);
        try {
            OutputStream os = textField.getOutputStream();
            wb.write(os);
            os.close();
            MultipartFile file = new CommonsMultipartFile(textField);
            return file;
        } catch (Exception e) {
            log.error("报表生成Excel文件上传失败");
            throw new CustomException("报表生成Excel文件上传失败:" + e.getMessage());
        }
    }

    private List<List<Map<String, String>>> getActiveData(List<String> columns, JSONArray jsonArray) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject data = jsonArray.getJSONObject(i);
            List<Map<String, String>> row = new ArrayList<>();
            for (String column : columns) {
                Map<String, String> map = new HashMap<>();
                column = StrUtil.equals(column, "时间") ? "time" : column;
                String str = data.getString(column);
                if (StrUtil.isBlank(str)) {
                    map.put("data", "");
                } else {
                    map.put("data", str);
                }
                map.put("name", column);
                row.add(map);
            }
            result.add(row);
        }
        return result;
    }

    /**
     * 根据列明和数值封装rows
     *
     * @param columns
     * @param jsonArray
     * @return
     */
    private List<List<Map<String, String>>> getData(List<String> columns, JSONArray jsonArray, List<ProductTelemetry> telemetries) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject data = jsonArray.getJSONObject(i);
            List<Map<String, String>> row = new ArrayList<>();
            for (String column : columns) {
                Map<String, String> map = new HashMap<>();
                column = StrUtil.equals(column, "时间") ? "time" : column;
                //获取数据类型
                String finalColumn = column;
                telemetries.forEach(a -> {
                    if (StrUtil.equals(a.getUserIdentifier(), finalColumn)) {
                        if (finalColumn.contains("__active")) {
                            map.put("dataType", "STRING");
                        } else {
                            map.put("dataType", a.getDataType());
                        }
                    }
                });
                String str = data.getString(column);
                if (StrUtil.isBlank(str)) {
                    map.put("data", "");
                } else {
                    map.put("data", str);
                }
                map.put("name", column);
                row.add(map);
            }
            result.add(row);
        }
        return result;
    }

    /**
     * 根据类型获取字段
     *
     * @param type
     * @return
     */
    private List<Map<String, String>> getAllColumn(String type) {
        List<Map<String, String>> result = new ArrayList<>();
        if (StrUtil.equals(type, "1")) {
            //项目列表
            Map<String, String> map1 = new HashMap<>();
            map1.put("name", "名称");
            map1.put("field", "name");
            result.add(map1);
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "合同号");
            map2.put("field", "code");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "地址");
            map3.put("field", "address");
            result.add(map3);
            Map<String, String> map4 = new HashMap<>();
            map4.put("name", "状态");
            map4.put("field", "isOn");
            result.add(map4);
        } else if (StrUtil.equals(type, "2")) {
            //产品列表
            Map<String, String> map1 = new HashMap<>();
            map1.put("name", "名称");
            map1.put("field", "name");
            result.add(map1);
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "厂商");
            map2.put("field", "manufacturer");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "代码");
            map3.put("field", "code");
            result.add(map3);
            Map<String, String> map4 = new HashMap<>();
            map4.put("name", "备注");
            map4.put("field", "description");
            result.add(map4);
        } else if (StrUtil.equals(type, "3")) {
            //报警列表
            Map<String, String> map1 = new HashMap<>();
            map1.put("name", "所属项目");
            map1.put("field", "projectName");
            result.add(map1);
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "报警规则名称");
            map2.put("field", "ruleName");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "报警规则描述");
            map3.put("field", "description");
            result.add(map3);
            Map<String, String> map4 = new HashMap<>();
            map4.put("name", "报警等级");
            map4.put("field", "severityString");
            result.add(map4);
            Map<String, String> map5 = new HashMap<>();
            map5.put("name", "报警状态");
            map5.put("field", "status");
            result.add(map5);
            Map<String, String> map6 = new HashMap<>();
            map6.put("name", "发生时间");
            map6.put("field", "start");
            result.add(map6);
            Map<String, String> map7 = new HashMap<>();
            map7.put("name", "恢复时间");
            map7.put("field", "end");
            result.add(map7);
        } else if (StrUtil.equals(type, "4")) {
            //点检任务
            Map<String, String> map1 = new HashMap<>();
            map1.put("name", "名称");
            map1.put("field", "name");
            result.add(map1);
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "系统");
            map2.put("field", "system");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "开始时间");
            map3.put("field", "startTime");
            result.add(map3);
            Map<String, String> map4 = new HashMap<>();
            map4.put("name", "结束时间");
            map4.put("field", "endTime");
            result.add(map4);
            Map<String, String> map5 = new HashMap<>();
            map5.put("name", "执行人");
            map5.put("field", "nickName");
            result.add(map5);
            Map<String, String> map6 = new HashMap<>();
            map6.put("name", "状态");
            map6.put("field", "status");
            result.add(map6);
            Map<String, String> map7 = new HashMap<>();
            map7.put("name", "备注");
            map7.put("field", "remark");
            result.add(map7);
        } else if (StrUtil.equals(type, "5")) {
            //产品列表
            Map<String, String> map1 = new HashMap<>();
            map1.put("name", "名称");
            map1.put("field", "name");
            result.add(map1);
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "产品代码");
            map2.put("field", "sn");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "所属产品");
            map3.put("field", "productName");
            result.add(map3);
            Map<String, String> map5 = new HashMap<>();
            map5.put("name", "系统");
            map5.put("field", "system");
            result.add(map5);
            Map<String, String> map4 = new HashMap<>();
            map4.put("name", "位号");
            map4.put("field", "positionNumber");
            result.add(map4);
            Map<String, String> map6 = new HashMap<>();
            map6.put("name", "描述");
            map6.put("field", "description");
            result.add(map6);
            Map<String, String> map7 = new HashMap<>();
            map7.put("name", "状态");
            map7.put("field", "discarded");
            result.add(map7);
        } else if (StrUtil.equals(type, "sj")) {
            //事件列表
            Map<String, String> map1 = new HashMap<>();
            map1.put("name", "事件名称");
            map1.put("field", "eventName");
            result.add(map1);
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "事件参数");
            map2.put("field", "param");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "时间戳");
            map3.put("field", "timestamp");
            result.add(map3);
        } else if (StrUtil.equals(type, "7")) {
            //膨胀节销售统计
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "客户名称");
            map2.put("field", "deptName");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "项目名称");
            map3.put("field", "projectName");
            result.add(map3);
            Map<String, String> map4 = new HashMap<>();
            map4.put("name", "合同号");
            map4.put("field", "projectCode");
            result.add(map4);
            Map<String, String> map6 = new HashMap<>();
            map6.put("name", "合同金额");
            map6.put("field", "amount");
            result.add(map6);
            Map<String, String> map5 = new HashMap<>();
            map5.put("name", "产品数量");
            map5.put("field", "deviceNum");
            result.add(map5);
        } else if (StrUtil.equals(type, "8")) {
            //膨胀节销售统计
            Map<String, String> map2 = new HashMap<>();
            map2.put("name", "客户名称");
            map2.put("field", "deptName");
            result.add(map2);
            Map<String, String> map3 = new HashMap<>();
            map3.put("name", "项目名称");
            map3.put("field", "projectName");
            result.add(map3);
//            Map<String, String> map4 = new HashMap<>();
//            map4.put("name", "合同号");
//            map4.put("field", "projectCode");
//            result.add(map4);
            Map<String, String> map8 = new HashMap<>();
            map8.put("name", "产品名称");
            map8.put("field", "deviceName");
            result.add(map8);
            Map<String, String> map5 = new HashMap<>();
            map5.put("name", "产品代码");
            map5.put("field", "sn");
            result.add(map5);
            Map<String, String> map9 = new HashMap<>();
            map9.put("name", "处理次数");
            map9.put("field", "dealTimes");
            result.add(map9);
            Map<String, String> map6 = new HashMap<>();
            map6.put("name", "异常位置");
            map6.put("field", "errorAddress");
            result.add(map6);
            Map<String, String> map7 = new HashMap<>();
            map7.put("name", "发生时间");
            map7.put("field", "time");
            result.add(map7);
        }
        return result;
    }

    /**
     * 获取项目详情数据
     *
     * @param allColumn
     * @param projectList
     * @return
     */
    private List<List<Map<String, String>>> getProjectData(List<Map<String, String>> allColumn, List<Project> projectList) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (Project project : projectList) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(project);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                String fieldValue = Convert.toStr(toMap.get(field));
                if ("isOn".equals(field)) {
                    fieldValue = StrUtil.equals(fieldValue, "1") ? "启用" : "未启用";
                }
                Map<String, String> valueMap = new HashMap<>();
                valueMap.put("dataType", "string");
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取型号详情数据
     *
     * @param allColumn
     * @param productList
     * @return
     */
    private List<List<Map<String, String>>> getProductData(List<Map<String, String>> allColumn, List<Product> productList) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (Product product : productList) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(product);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                String fieldValue = Convert.toStr(toMap.get(field));
                Map<String, String> valueMap = new HashMap<>();
                valueMap.put("data", fieldValue);
                valueMap.put("dataType", "string");
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取报警详情数据
     *
     * @param allColumn
     * @param alarmList
     * @return
     */
    private List<List<Map<String, String>>> getAlarmData(List<Map<String, String>> allColumn, List<Alarm> alarmList) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (Alarm alarm : alarmList) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(alarm);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                String fieldValue = null;
                if (StrUtil.equals(field, "start") || StrUtil.equals(field, "end")) {
                    Date date = Convert.toDate(toMap.get(field));
                    fieldValue = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
                } else {
                    fieldValue = Convert.toStr(toMap.get(field));
                }
                Map<String, String> valueMap = new HashMap<>();
                valueMap.put("dataType", "string");
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取点检任务详情数据
     *
     * @param allColumn
     * @param pointCheckTaskList
     * @return
     */
    private List<List<Map<String, String>>> getPointCheckData(List<Map<String, String>> allColumn, List<PointCheckTask> pointCheckTaskList) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (PointCheckTask pointCheckTask : pointCheckTaskList) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(pointCheckTask);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                String fieldValue = null;
                if (StrUtil.equals(field, "startTime") || StrUtil.equals(field, "endTime")) {
                    Date date = Convert.toDate(toMap.get(field));
                    fieldValue = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
                } else if (StrUtil.equals(field, "status")) {
                    String status = Convert.toStr(toMap.get(field));
                    fieldValue = StrUtil.equals(status, "0") ? "未开始" : StrUtil.equals(status, "1") ? "进行中" : StrUtil.equals(status, "2") ? "已超时" : "已完成";
                } else {
                    fieldValue = Convert.toStr(toMap.get(field));
                }
                Map<String, String> valueMap = new HashMap<>();
                valueMap.put("dataType", "string");
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取产品详情数据
     *
     * @param allColumn
     * @param deviceList
     * @return
     */
    private List<List<Map<String, String>>> getDeviceData(List<Map<String, String>> allColumn, List<Device> deviceList) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (Device device : deviceList) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(device);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                String fieldValue = null;
                if (StrUtil.equals(field, "discarded")) {
                    fieldValue = StrUtil.equals(Convert.toStr(toMap.get(field)), "false") ? "正常" : "报废";
                } else {
                    fieldValue = Convert.toStr(toMap.get(field));
                }
                Map<String, String> valueMap = new HashMap<>();
                valueMap.put("dataType", "string");
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取膨胀节销售统计详情数据
     *
     * @param allColumn
     * @param salesSummaryVOS
     * @return
     */
    private List<List<Map<String, String>>> getSalesSummaryData(List<Map<String, String>> allColumn, List<SalesSummaryVO> salesSummaryVOS) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (SalesSummaryVO summaryVO : salesSummaryVOS) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(summaryVO);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                Map<String, String> valueMap = new HashMap<>();
                if (field.equals("amount") || field.equals("deviceNum")) {
                    valueMap.put("dataType", "decimal");
                } else {
                    valueMap.put("dataType", "string");
                }
                String fieldValue = Convert.toStr(toMap.get(field));
//                if (StrUtil.equals(field, "isOn")) {
//                    fieldValue = StrUtil.equals(Convert.toStr(toMap.get(field)), "1") ? "启用" : "停用";
//                } else {
//                    fieldValue = Convert.toStr(toMap.get(field));
//                }
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取膨胀节销售统计详情数据
     *
     * @param allColumn
     * @param salesSummaryVOS
     * @return
     */
    private List<List<Map<String, String>>> getDeviceStatusSummaryData(List<Map<String, String>> allColumn, List<DeviceStatusSummaryVO> salesSummaryVOS) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (DeviceStatusSummaryVO summaryVO : salesSummaryVOS) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(summaryVO);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                Map<String, String> valueMap = new HashMap<>();
                if (field.equals("dealTimes")){
                    valueMap.put("dataType", "decimal");
                }else {
                    valueMap.put("dataType", "string");
                }
                String fieldValue = null;
                if (StrUtil.equals(field, "time")) {
                    Date date = Convert.toDate(toMap.get(field));
                    fieldValue = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
                } else {
                    fieldValue = Convert.toStr(toMap.get(field));
                }
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }

    /**
     * 获取事件详情数据
     *
     * @param allColumn
     * @param terminalEventDetailList
     * @return
     */
    private List<List<Map<String, String>>> getEventData(List<Map<String, String>> allColumn, List<TerminalEventDetail> terminalEventDetailList) {
        List<List<Map<String, String>>> result = new ArrayList<>();
        for (TerminalEventDetail eventDetail : terminalEventDetailList) {
            List<Map<String, String>> data = new ArrayList<>();
            Map<String, Object> toMap = BeanUtil.beanToMap(eventDetail);
            for (Map<String, String> map : allColumn) {
                //String name = map.get("name");
                String field = map.get("field");
                String fieldValue = null;
                if (StrUtil.equals(field, "timestamp")) {
                    Date date = Convert.toDate(toMap.get(field));
                    fieldValue = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
                } else {
                    fieldValue = Convert.toStr(toMap.get(field));
                }
                Map<String, String> valueMap = new HashMap<>();
                valueMap.put("dataType", "string");
                valueMap.put("data", fieldValue);
                data.add(valueMap);
            }
            result.add(data);
        }
        return result;
    }
}
